package com.sites.cds.common.directive;

import java.io.IOException;

import com.jfinal.template.Directive;
import com.jfinal.template.Env;
import com.jfinal.template.TemplateException;
import com.jfinal.template.expr.ast.Expr;
import com.jfinal.template.expr.ast.ExprList;
import com.jfinal.template.io.Writer;
import com.jfinal.template.stat.ParseException;
import com.jfinal.template.stat.Scope;

/**
 * 字符串截取指令
 * 两种用法：
 * cutStr(string, length)两个参数分别是原字符串、要保留的字符串长度，默认拼接...
 * cutStr(string, length, pattern)三个参数分别是原字符串、要保留的字符串长度、截取后拼接的内容
 * 
 * @author zyg
 * 2019年12月22日 下午9:39:07
 */
public class CutStringDirective extends Directive {

	private Expr valueExpr;
	private Expr strLenExpr;
	private Expr patternExpr;
	private int paraNum;
	
	private String defaultPattern = "...";
	
	@Override
	public void setExprList(ExprList exprList) {
		this.paraNum = exprList.length();
		if (paraNum > 3 || paraNum < 2) {
			throw new ParseException("Wrong number parameter of #cutStr directive, two parameters or three parameters are allowed here", location);
		}
		
		if (paraNum == 2) {
			this.valueExpr = exprList.getExpr(0);
			this.strLenExpr = exprList.getExpr(1);
			this.patternExpr = null;
		} else if (paraNum == 3) {
			this.valueExpr = exprList.getExpr(0);
			this.strLenExpr = exprList.getExpr(1);
			this.patternExpr = exprList.getExpr(2);
		}
	}
	
	@Override
	public void exec(Env env, Scope scope, Writer writer) {
		Object value = valueExpr.eval(scope);
		Object strLen = strLenExpr.eval(scope);
		
		if(paraNum == 2) {//两个参数
			if(value instanceof String){
				if(strLen instanceof Integer){
					write(writer, (String)value, (Integer)strLen, defaultPattern);
				} else {
					throw new TemplateException("The second parameter length of #cutStr directive must be Integer type", location);
				}
			} else {
				throw new TemplateException("The first parameter string of #cutStr directive must be String type", location);
			}
		} else if(paraNum == 3){//三个参数
			Object pattern = patternExpr.eval(scope);
			if(value instanceof String){
				if(strLen instanceof Integer){
					if(pattern instanceof String){
						write(writer, (String)value, (Integer)strLen, (String)pattern);
					} else {
						throw new TemplateException("The third parameter pattern of #cutStr directive must be String type", location);
					}
				} else {
					throw new TemplateException("The second parameter length of #cutStr directive must be Integer type", location);
				}
			} else {
				throw new TemplateException("The first parameter string of #cutStr directive must be String type", location);
			}
		}

	}
	
	private void write(Writer writer, String string, int strLen, String pattern) {
		try {
			if(string.length() > strLen){
				writer.write(string.substring(0, strLen) + pattern);
			} else {
				writer.write(string);
			}
		} catch (IOException e) {
			throw new TemplateException(e.getMessage(), location, e);
		}
	}
}
